
package sg.edu.nus.iss.cats.dataaccess.mysql;

import sg.edu.nus.iss.cats.dataaccess.*;

import java.util.*;

public class SequenceManagerImpl implements SequenceManager {

    private static final int ALLOCATION_SIZE = 1;
    private Hashtable seq = new Hashtable ();

    public int getNextValue (String sequenceName) throws DAOException {
        // Get the sequence info from the table
        SequenceInfo info = (SequenceInfo) seq.get (sequenceName);

        // If there is no sequence info, or we're at the end of our 
        // allocation, get the latest allocation from the db
        if ((info == null) || (info.getNextValue() > info.getLastValue())) {
            info = allocateNewValues (sequenceName);
            seq.put (sequenceName, info);
        }

        // Return the first available value and increment
        int result = info.getNextValue ();
        info.setNextValue (result + 1);
        return result;
    }

    private SequenceInfo allocateNewValues (String sequenceName)
                    throws DAOException {
        SQLObjectManager mgr = new SQLObjectManager (
            new SequenceObjectHandler ());
        String constraint = DBConstants.seq_name  + "='" + sequenceName + "'";
        mgr.setQueryConstraint (constraint);
        SequenceInfo info = (SequenceInfo) mgr.getObject ();
        if (info == null) {
            
            info = startNewSequence (sequenceName);
        }
        int lastValue = info.getLastValue();
        info.setNextValue(lastValue + 1);
        info.setLastValue(lastValue + ALLOCATION_SIZE);
        mgr.updateObject (info);
        return info;
    }

    private SequenceInfo startNewSequence (String sequenceName)
                    throws DAOException {
        SequenceInfo info = new SequenceInfo ();
        info.setName(sequenceName);
        info.setLastValue (0);
        SQLObjectManager mgr = new SQLObjectManager (
            new SequenceObjectHandler ());
        mgr.createObject (info);
        return info;
    }

}
